package org.syx.edl.db;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.syx.edl.ItemReader;
import org.syx.edl.RowMapper;

import java.sql.*;

/**
 * @author:whh
 * @date: 2025-05-20 22:38
 * <p></p>
 */
public class JdbcCursorReader<T> implements ItemReader<T>{
    public static Logger logger = LoggerFactory.getLogger(JdbcCursorReader.class);
    private Connection conn;
    private String sql;
    private PreparedStatementSetter pst;
    private RowMapper rowMapper;

    private PreparedStatement ps;
    private ResultSet rs;
    private int rowNum;



    public JdbcCursorReader() {
    }

    public JdbcCursorReader(Connection conn,
                            String sql,
                            PreparedStatementSetter pst,
                            RowMapper rowMapper) {
        this.conn = conn;
        this.sql = sql;
        this.pst = pst;
        this.rowMapper = rowMapper;
    }

    @Override
    public void open() throws Exception {
        try{
            if (conn == null) {
                throw new IllegalArgumentException("connection cannot be null");
            }
            if (sql == null) {
                throw new IllegalArgumentException("sql cannot be null");
            }
            if(rowMapper == null){
                rowMapper= new DefaultMapRowMapper();
            }
            ps=conn.prepareStatement(sql,ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
            ps.setFetchSize(50);
            ps.setFetchDirection(ResultSet.FETCH_FORWARD);//按游标从头到尾取数
            if(pst!=null){
                pst.setValues(ps);
            }
            rs=ps.executeQuery();
        }catch (Exception ex){
            close();
            logger.error("数据库游标打开异常",ex);
            throw ex;
        }
    }

    @Override
    public void flip() {

    }

    @Override
    public void close()  {
        closeResultSet(rs);
        rs=null;
        closeStatement(ps);
        releaseConnection(conn);
    }

    @Override
    public boolean hasNext() {
        try {
            return rs.next();
        } catch (SQLException e) {
            logger.error("数据库移动游标异常",e);
            return false;
        }
    }

    @Override
    public T next() {
        try {
            return (T) rowMapper.mapRow(rs, rowNum++);
        } catch (SQLException e) {
            logger.error("数据映射异常",e);
            return null;
        }
    }



    public void closeStatement( Statement stmt) {
        if (stmt != null) {
            try {
                stmt.close();
            }
            catch (SQLException ex) {
                logger.trace("Could not close JDBC Statement", ex);
            }
            catch (Throwable ex) {
                // We don't trust the JDBC driver: It might throw RuntimeException or Error.
                logger.trace("Unexpected exception on closing JDBC Statement", ex);
            }
        }
    }



    public  void releaseConnection(Connection con) {
        try {
            if (con != null) {
                con.close();
            }
        }
        catch (SQLException ex) {
            logger.debug("Could not close JDBC Connection", ex);
        }
        catch (Throwable ex) {
            logger.debug("Unexpected exception on closing JDBC Connection", ex);
        }
    }



    public void closeResultSet(ResultSet rs) {
        if (rs != null) {
            try {
                rs.close();
            }
            catch (SQLException ex) {
                logger.trace("Could not close JDBC ResultSet", ex);
            }
            catch (Throwable ex) {
                // We don't trust the JDBC driver: It might throw RuntimeException or Error.
                logger.trace("Unexpected exception on closing JDBC ResultSet", ex);
            }
        }
    }


    public String getSql() {
        return sql;
    }

    public int getRowNum() {
        return rowNum;
    }
}
